using System.Collections.ObjectModel;
using System.Threading;
using StructureMap;

namespace Medianamik.Core.Redirect
{
    public class ExternalRedirectDictionary : KeyedCollection<string, ExternalRedirect>
    {
        private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
        //Voir http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

        public ExternalRedirectDictionary()
        {
            Initialize();
        }

        private void Initialize()
        {
            ObjectFactory.GetInstance<IExternalRedirectUrlRepository>().GetAllExternalRedirect().ForEach(AddSafe);
        }

        public static ExternalRedirectDictionary Instance
        {
            get
            {
                return Singleton<ExternalRedirectDictionary>.Instance;
            }
        }

        public ExternalRedirect GetEntry(string pUri)
        {
            pUri = (pUri ?? string.Empty).ToLowerInvariant();
            _lock.EnterReadLock();
            try
            {
                if (this.Contains(pUri))
                {
                    return this[pUri];
                }
                return null;
            }
            finally
            {
                _lock.ExitReadLock();
            }
        }

        public bool ContainsUrl(string pUrl)
        {
            _lock.EnterReadLock();
            try
            {
                return Contains((pUrl ?? string.Empty).ToLowerInvariant());
            }
            finally
            {
                _lock.ExitReadLock();
            }
        }

        public void Reload()
        {
            _lock.EnterWriteLock();
            try
            {
                Clear();
                Initialize();
            }
            finally
            {
                _lock.ExitWriteLock();
            }
        }

        protected override string GetKeyForItem(ExternalRedirect item)
        {
            return item.RedirectFrom.ToLowerInvariant();
        }

        public void AddSafe(ExternalRedirect externalRedirect)
        {
            if (!Contains(GetKeyForItem(externalRedirect)))
                Add(externalRedirect);
        }

        public void AddSafe(ExternalRedirectNode node)
        {
            var er = new ExternalRedirect(node.DefaultInstance[MedianamikProperties.MedianamikRedirectFrom].GetValue<string>(),
                node.DefaultInstance[MedianamikProperties.MedianamikRedirectTo].GetValue<string>(),
                node.DefaultInstance[MedianamikProperties.MedianamikRedirectCode].GetValue<int>());

            if (!Contains(GetKeyForItem(er)))
                Add(er);
        }
    }

    public class ExternalRedirect : IRedirectNode
    {
        public ExternalRedirect(string redirectFrom, string redirectTo, int responseCode)
        {
            RedirectFrom = redirectFrom;
            RedirectTo = redirectTo;
            ResponseCode = responseCode;
        }

        public string RedirectFrom { get; private set; }

        public int ResponseCode { get; private set; }

        public string RedirectTo { get; private set; }
    }
}